/**
 * 
 *  @project Air Traff Monitor
 * 
 *  @author M.Emre ATASEVER <m.emre.atas@gmail.com>
 *  @author M.Burak ALKAN <mburakalkan@gmail.com>
 *  @author H.Burak KARAMIK <bkaramik@gmail.com>
 *
 *	`Air Traffic Monitor' is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "netmodel.h"
#include <QtAlgorithms>

NetworkModel::NetworkModel(QKismetSocket *sock) : KismetDataModel<NetworkRootItem,NetworkItem>(sock) 
{
	connect(socket,SIGNAL(netInfo(networkInfo)),this,SLOT(netInfo(networkInfo)));
	connect(socket,SIGNAL(cliInfo(clientInfo)),this,SLOT(cliInfo(clientInfo)));
}

QVariant NetworkModel::data(const QModelIndex &index, int role) const
{
	if(!index.isValid())
		return QVariant();
	if(role == Qt::TextColorRole)
	{
		NetmodelItem *item	= static_cast<NetmodelItem*>(index.internalPointer());
		if(item->hasColor)
			return item->color;
		else
			return QVariant();
	}
	else if(role == Qt::DisplayRole || role == Qt::UserRole)
	{
		NetmodelItem *item	= static_cast<NetmodelItem*>(index.internalPointer());
		QVariant data	= item->data(index.column());
		if(role == Qt::UserRole)
			return data;
		else 
			return NetworkOptions::print(&data,index.column());
	}
	return QVariant();
}

QVariant NetworkModel::headerData(int section, Qt::Orientation orientation,int role) const
{
	if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
		return socket->net.getNames()->at(section);
	return QVariant();
}

QModelIndex NetworkModel::index(int row, int column, const QModelIndex &parent) const
{
	if(!hasIndex(row,column,parent))
		return QModelIndex();
	
	if(!parent.isValid())
	{
		NetworkItem *it	= rootItem->items[row];
		if(it)
			return createIndex(row,column,it);
	}
	else
	{
		NetworkItem *it = static_cast<NetworkItem*>(parent.internalPointer());
		if(it)
		{
			ClientItem *cit	= it->items[row];
			if(cit)
				return createIndex(row,column,cit);
		}
	}
	return QModelIndex();
}

QModelIndex NetworkModel::parent(const QModelIndex &index) const
{
	if(!index.isValid())
		return QModelIndex();

	NetmodelItem *childItem = static_cast<NetmodelItem*>(index.internalPointer());
	NetmodelItem *parentItem = (NetmodelItem*)childItem->parent();

	if (parentItem == (NetmodelItem*)rootItem)
		return QModelIndex();

	return createIndex(parentItem->row(), 0, parentItem);
}

int NetworkModel::columnCount(const QModelIndex&) const
{
	return socket->net.getNames()->size();
}

int NetworkModel::rowCount(const QModelIndex &parent) const
{
	if(!parent.isValid())
		return rootItem->items.size();
	NetmodelItem *item = static_cast<NetmodelItem*>(parent.internalPointer());
	return item->rowCount();
}

void NetworkModel::netInfo(networkInfo info)
{
	QString bssid = info.props[0].toString();
	NetworkItem* item	= findItem(bssid);

	int mscore	= info.props[info.idx->indexOf(16)].toInt();
	int enc		= info.props[info.idx->indexOf(6)].toInt();
	
	if(item)
	{
		//Update existing item
		if(mscore || enc)
		{
			(enc) ? item->color.setRgb(0,220,0) : item->color.setRgb(135+15*mscore,0,0);
			item->hasColor	= true;
		}
		else
			item->hasColor	= false;
		
		int s	= info.idx->size();
		if(s > 1)
		{
			item->setData(&info);
			int r 	= item->row();
			emit dataChanged(createIndex(r,info.idx->at(1),item),createIndex(r,info.idx->at(s-1),item));
		}
	}
	else
	{
		int c	= rootItem->items.size();
		beginInsertRows(QModelIndex(),c,c);
		item	= new NetworkItem(&info,rootItem);
		if(mscore || enc)
		{
			(enc) ? item->color.setRgb(0,220,0) : item->color.setRgb(135+15*mscore,0,0);
			item->hasColor	= true;
		}
		rootItem->items.append(item);

		
		endInsertRows();

	}
}

void NetworkModel::cliInfo(clientInfo info)
{
	QString bssid	= info.props[0].toString();
	QString mac	= info.props[1].toString();
	NetworkItem* item	= findItem(bssid);

	int mscore	= info.props[info.idx->indexOf(6)].toInt();
	int enc		= info.props[info.idx->indexOf(39)].toInt();
	
	if(item)
	{
		//Found network...
		//Find this client
		ClientItem *cli	= 0;

		int j	= item->items.size();
		for(int i = 0;i < j;i++)
			if(item->items[i]->bssid == mac)
			{
				cli	=  item->items[i];
				break;
			}
		if(cli)
		{
			//Update existing item
			if(mscore || enc)
			{
				(enc) ? cli->color.setRgb(0,220,0) : cli->color.setRgb(135+15*mscore,0,0);
				cli->hasColor	= true;
			}
			else
				cli->hasColor	= false;
			
			int s	= info.idx->size();
			if(s > 1)
			{
				cli->setData(&info);
				int r 	= cli->row();
				emit dataChanged(createIndex(r,info.idx->at(1),cli),createIndex(r,info.idx->at(s-1),cli));
			}
		}
		else
		{
			int c	= item->items.size();
			beginInsertRows(createIndex(item->row(),0,item),c,c);
			item->addClient(&info);
			if(mscore || enc)
			{
				(enc) ? item->color.setRgb(0,220,0) : item->color.setRgb(135+15*mscore,0,0);
				item->hasColor	= true;
			}

			endInsertRows();
		}

	}
}
NetworkItem* NetworkModel::findItem(QString& bssid)
{
	int j	= rootItem->items.size();
	for(int i = 0;i < j;i++)
		if(rootItem->items[i]->bssid == bssid)
			return rootItem->items[i];
	return 0;
}
